#include "AVL.h"
#include "Structs.h"

using namespace std;
AVL::AVL()
{
    Raiz=NULL;
}

void AVL::Insertar(int clave, int dato1, string dato2)
{
        //InsertarBalanceado(clave,dato1,dato2,&Raiz,false);
        Cliente str;
        str.Licencia=dato1;
        str.Nombre=dato2;
        Insertar(clave,str);
        VIFS::V_WriteLog("VL: insercion");
}
/*
void AVL::InsertarBalanceado(int clave, int dato1, string dato2, NodoArbol<Cliente> **raiz, bool Hh)
{
    NodoArbol<Cliente> * n1;
    //pNodoBinario n1;

    //if(Raiz == NULL){
    if(Vacio(*raiz)){
    //if(raiz==NULL){
        Cliente temp;
        temp.Licencia = dato1;
        temp.Nombre = dato2;
        *raiz = new NodoArbol<Cliente>(clave,temp); //(clave,temp);
        //ra=new NodoBinario(x);
            //cout<<ra->valor<<"q as"<<endl;
        Hh = true;
    }
    else
    {
        //cout<<"q as2"<<endl;
        if (clave < (*raiz)->getClave())
        {
            //if(x<ra->valor){
            InsertarBalanceado(clave,dato1,dato2,((*raiz)->getHizq()),Hh);
            //InsertarBalanceado(ra->Hizq, Hh, x);
            if (Hh==true)
            {
                //if(Hh){
                switch((*raiz)->getClave())
                {
                //switch(ra->valor){
                case 1: (*raiz)->setFB(0);
                    //case 1: ra->FB=0;
                    Hh = false;
                    break;

                case 0:  (*raiz)->setFB(-1);
                    //case 0: ra->FB  = -1;
                    break;

                case -1: n1 = (*raiz)->getHizq();
                    //case -1: n1=ra->Hizq;
                    if (n1->getFB() == -1){
                        //if(n1->FB =-1){
                        RotacionSimpleIzquierda(*raiz, n1);
                        //RotacionSimpleIzquierda(ra, n1);
                    }
                    else
                    {
                        RotacionDobleIzquierda(*raiz, n1);
                        //RotacionDobleIzquierda(ra,n1);
                    }
                    Hh = false;
                    break;
                }
            }   //sobra
        }
        else
        {
            if (clave > *raiz->getClave())
            {
                //if(x>ra->valor){
                InsertarBalanceado(clave,dato1,dato2,*raiz->getHder(),Hh);
                //InsertarBalanceado(ra->Hder, Hh, x);
                if (Hh == true)
                {
                    //if(Hh){
                    switch(*raiz->getFB())
                    {
                    //switch(ra->FB){
                    case -1: *raiz->setFB(0);
                        //case -1: ra->FB=0;
                        Hh = false;
                        break;

                    case 0: *raiz->setFB(1);
                        //case 0: ra->FB=1;
                        break;

                    case 1: n1 = *raiz->getHder();
                        //case 1:n1=ra->Hder;
                        if(n1->getFB() == 1)
                        {
                            //if(n1->FB=1){
                            RotacionSimpleDerecha(*raiz,n1);
                            //RotacionSimpleDerecha(ra, n1);
                        }
                        else
                        {
                            RotacionDobleDerecha(*raiz,n1);
                            //RotacionDobleDerecha(ra, n1);
                        }
                        Hh=false;
                        break;
                    }
                }
            }
        }
    }

}

*/

void AVL::Insertar(int clave, Cliente c)
{
    if(Vacio())
        Raiz=new NodoArbol<Cliente>(clave,c,2);
    else
    {
        bool Hh_np=false;
        bool* Hh= &Hh_np;
        Insertar(clave,c,&Raiz,Hh);
    }
}

void AVL::Insertar(int clave, Cliente c, NodoArbol<Cliente> **raiz, bool* Hh)
{
    if(clave < (*raiz)->getClave())
    {
        NodoArbol<Cliente> *temp=(*raiz)->getHizq();
        if(Vacio(temp))
        {
            (*raiz)->setHizq(new NodoArbol<Cliente>(clave,c,2));
            *Hh=true;
        }
        else
            Insertar(clave,c,((*raiz)->getHHizq()),Hh);
        if(*Hh)
        {
            switch ((*raiz)->getFB())
            {
            case 1:
                (*raiz)->setFB(0);
                *Hh=false;
                break;
            case 0:
                (*raiz)->setFB(-1);
                break;
            case -1:
                NodoArbol<Cliente> * n1=(*raiz)->getHizq();
                if(n1->getFB()==-1)
                    RotacionSimpleIzquierda(raiz,&n1);
                else
                    RotacionDobleIzquierda(raiz,&n1);
                *Hh=false;
                break;
            }
        }
    }
    else
    {
        if(clave > (*raiz)->getClave())
        {
            NodoArbol<Cliente> *temp=(*raiz)->getHder();
            if(Vacio(temp))
            {
                (*raiz)->setHder(new NodoArbol<Cliente>(clave,c,2));
                *Hh=true;
            }
            else
                Insertar(clave,c,((*raiz)->getHHder()),Hh);
            if(*Hh)
            {
                switch((*raiz)->getFB())
                {
                case -1:
                    (*raiz)->setFB(0);
                    *Hh=false;
                    break;
                case 0:
                    (*raiz)->setFB(1);
                    break;
                case 1:
                    NodoArbol<Cliente> * n1=(*raiz)->getHder();
                    if(n1->getFB()==1)
                        RotacionSimpleDerecha(raiz,&n1);
                    else
                        RotacionDobleDerecha(raiz,&n1);
                    *Hh=false;
                    break;
                }
            }
        }
    }
}


void AVL::RotacionDobleIzquierda(NodoArbol<Cliente> **n, NodoArbol<Cliente> **n1)
{
    NodoArbol<Cliente> * n2;
    //NodoBinario *n2;
    n2 = (*n1)->getHder();
    //n2=n1->Hder;
    (*n)->setHizq(n2->getHder());
    //n->Hizq = n2->Hder;
    n2->setHder(*n);
    //n2->Hder=n;
    (*n1)->setHder(n2->getHizq());
    //n1->Hder=n2->Hizq;
    n2->setHizq(*n1);
    //n2->Hizq=n1;
    if (n2->getFB()==1)
    {
    //if(n2->FB==1){
        (*n1)->setFB(-1);
        //n1->FB=-1;
    }
    else
    {
        (*n1)->setFB(0);
        //n1->FB=0;
    }
    if(n2->getFB()==-1){
    //if(n2->FB==-1){
        (*n)->setFB(1);
        //n->FB=1;
    }
    else
    {
        (*n)->setFB(0);
        //n->FB=0;
    }
    n2->setFB(0);
    //n2->FB=0;
    *n=n2;
    VIFS::V_WriteLog("AVL: RDI");

}

void AVL::RotacionDobleDerecha(NodoArbol<Cliente> **n, NodoArbol<Cliente> **n1)
{
    NodoArbol<Cliente> * n2;
    //NodoBinario *n2;
    n2 = (*n1)->getHizq();
    //n2=n1->Hizq;
    (*n)->setHder(n2->getHizq());
    //n->Hder = n2->Hizq;
    n2->setHizq(*n);
    //n2->Hizq=n;
    (*n1)->setHizq(n2->getHder());
    //n1->Hizq=n2->Hder;
    n2->setHder(*n1);
    //n2->Hder=n1;
    if (n2->getFB()==1)
    {
    //if(n2->FB==1){
        (*n)->setFB(-1);    //
        //n->FB=-1;
    }
    else
    {
        (*n)->setFB(0);    //
        //n->FB=0;
    }
    if(n2->getFB()==-1){
    //if(n2->FB==-1){
        (*n1)->setFB(1);   //
        //n1->FB=1;
    }else{
        (*n1)->setFB(0);   //
        //n1->FB=0;
    }
    n2->setFB(0);
    //n2->FB=0;
    *n=n2;
    VIFS::V_WriteLog("AVL: RDD");

}



void AVL::RotacionSimpleDerecha(NodoArbol<Cliente> **n, NodoArbol<Cliente> **n1)
{
    (*n)->setHder((*n1)->getHizq());
    //n->Hder=n1->Hizq;
    (*n1)->setHizq(*n);
    //n1->Hizq=n;
    if ((*n1)->getFB()==1){
    //if(n1->FB==1){
        (*n)->setFB(0);
        //n->FB=0;
        (*n1)->setFB(0);
        //n1->FB=0;
    }
    else
    {
        (*n)->setFB(1);
        //n->FB=1;
        (*n1)->setFB(-1);
        //n1->FB=-1;
     }
        *n=*n1;
    VIFS::V_WriteLog("AVL: RSD");

}


void AVL::RotacionSimpleIzquierda(NodoArbol<Cliente> **n, NodoArbol<Cliente> **n1)
{
    (*n)->setHizq((*n1)->getHder());
    //n->Hizq=n1->Hder;
    (*n1)->setHder(*n);
    //n1->Hder=n;
    if ((*n1)->getFB()==-1){   //
    //if(n1->FB==-1){
        (*n)->setFB(0);
        //n->FB=0;
        (*n1)->setFB(0);
        //n1->FB=0;
    }else{
        (*n)->setFB(1);
        //n->FB=-1;
        (*n1)->setFB(-1);
        //n1->FB=-1;
    }
    *n=*n1;
    VIFS::V_WriteLog("AVL RSI");
}
